IntentMemoryStorage
IntentMemoryStorage 是一个用于 在多个 AppIntent 执行之间保留临时数据 的内存存储系统。然而,它的生命周期并不严格绑定在单次 AppIntent 或 Script.exit 以上,而是由系统对 Extension 环境(Intent Extension / Widget Extension)的运行状态决定,因此具有一定的非确定性。
以下文档基于你之前确认的完整版结构,并加入系统行为的解释。
概述
在 Scripting 中,每个 AppIntent 都运行在其所属脚本的 脚本执行上下文(Script Execution Context) 中。当 AppIntent 的 perform() 执行完成,或在 intent.tsx 中调用 Script.exit() 时,当前 AppIntent 的执行流程会结束。
但关键点是:
IntentMemoryStorage 不会在 AppIntent 或 Script.exit 结束时被立即销毁
它的生命周期依赖于:
- 系统是否继续保留当前 Extension 进程
- 系统是否因为内存压力或其他策略回收 Extension
- Widget 或 Live Activity 是否仍在使用同一 Extension
因此:
- 在 Shortcuts 再次运行同一个脚本时
有可能读取到上次设置的 MemoryStorage 值
- 在 Widget 或 Live Activity 中调用 AppIntent
同一个脚本的 JS Context 可能被重用,因此 MemoryStorage 也会保留
- 系统何时清除 MemoryStorage 不可预测
MemoryStorage 的本质是:
存储在当前 Extension 进程中的短期内存,非持久化、非可靠、非严格会话级
作用范围(Scopes)
IntentMemoryStorage 提供两类存储区域:
1. 脚本级(Script-scoped)存储
默认行为。
- 属于单个脚本项目
- 脚本 A 不能访问脚本 B 的脚本级存储
- Extension 不被系统销毁时,会保留该脚本的存储
- Extension 一旦被销毁,存储也随之清空
适用于该脚本内部多步骤流程。
2. 共享(Shared)存储
使用 { shared: true } 可访问一个共享区域:
- 所有脚本的 AppIntent 都可访问
- 在 Extension 未被系统释放前可以持续存在
- Extension 被销毁后清空
适合在多个脚本之间协调状态。
Extension 生命周期与 JS Context 行为
情况一:在 Shortcuts 中运行 Intent
因此:
再次运行同一个脚本时,可能读到上次的数据。
例:
1IntentMemoryStorage.set("color", "red")
下一次 Shortcut 再运行时:
1const c = IntentMemoryStorage.get("color")
可能仍然得到 "red"。
这是系统层面的行为,并非 Scripting 的行为。
情况二:在小组件(Widget/Control Widget)中调用 AppIntent
Widget Extension 的特点:
- Scripting 会尽量复用 JS Context
- 即使 AppIntent 执行结束,JS Context 也可能继续存在
- 因此 MemoryStorage 也可能持续存在
但:
系统随时可能回收 Extension(尤其在内存压力下),JS Context 和 MemoryStorage 都会被清空。
情况三:Live Activity 调用 AppIntent
Live Activity Extension 也可能复用上下文:
- 多次调用 AppIntent 通常复用同一 JS Context
- MemoryStorage 可能继续保留
- 但系统没有保证稳定性
- 扩展环境被杀死后 MemoryStorage 立即失效
总结生命周期(非常关键)
| 行为 |
是否导致 MemoryStorage 清空 |
| AppIntent 执行结束 |
否 |
| Script.exit() |
否 |
| Shortcut 流程结束 |
不一定 |
| Widget 更新 AppIntent |
不一定 |
| Live Activity 调用 AppIntent |
不一定 |
| 系统回收 Extension 进程 |
是(彻底清空) |
MemoryStorage 的生命周期与 Extension 进程生命周期 完全一致,而 Extension 何时被系统保留/销毁是不可预测的系统行为。
API 定义
1namespace IntentMemoryStorage {
2 function get<T>(key: string, options?: { shared?: boolean }): T | null
3 function set(key: string, value: any, options?: { shared?: boolean }): void
4 function remove(key: string, options?: { shared?: boolean }): void
5 function contains(key: string, options?: { shared?: boolean }): boolean
6 function clear(): void
7 function keys(): string[]
8}
说明:
shared 仅作用于 get / set / remove / contains
- clear() 和 keys() 始终只针对脚本级存储区域
API 详细说明
get
1function get<T>(key: string, options?: { shared?: boolean }): T | null
读取键值。注意:
- 若 Extension 尚未被销毁,则可能读到上一次执行留下的值
- 若系统已清理 Extension,则可能返回 null
脚本级:
1const color = IntentMemoryStorage.get<string>("color")
shared:
1const token = IntentMemoryStorage.get<string>("token", { shared: true })
set
1function set(key: string, value: any, options?: { shared?: boolean }): void
写入存储区域。
脚本级:
1IntentMemoryStorage.set("color", "systemBlue")
shared:
1IntentMemoryStorage.set("sessionID", "abc123", { shared: true })
remove
1function remove(key: string, options?: { shared?: boolean }): void
删除键值。
脚本级:
1IntentMemoryStorage.remove("color")
shared:
1IntentMemoryStorage.remove("sessionID", { shared: true })
contains
1function contains(key: string, options?: { shared?: boolean }): boolean
检查键是否存在。
注意:此结果取决于当前 Extension 是否仍在。
clear
清空脚本级存储。
shared 区域不会被清空。
keys
1function keys(): string[]
返回脚本级存储的 key 列表。
使用场景
脚本级(默认)
适用于:
- 单脚本的多步骤流程
- 融合 SnippetIntent → AppIntent → SnippetIntent
- 临时保存当前 UI 状态、表单数据、步骤编号
示例:
1IntentMemoryStorage.set("step", 2)
shared(跨脚本)
适用于:
- 多脚本协同
- 工作流中跨多个项目传递会话状态
- 保存当前 Shortcut 全局状态
示例:
1IntentMemoryStorage.set("workflowID", "xyz", { shared: true })
不适用用途
- 不保证一定存在
- 不保证一定被清理
- 不适合存储大对象
- 不适合存储持久数据
- 不适合跨天或长期使用(可能在任何时间丢失)
推荐持久方案:
示例
脚本级示例
1IntentMemoryStorage.set("color", "red")
2
3const color = IntentMemoryStorage.get<string>("color")
shared 跨脚本示例
Script A:
1IntentMemoryStorage.set("sessionID", "12345", { shared: true })
Script B:
1const id = IntentMemoryStorage.get<string>("sessionID", { shared: true })
存储结构示例
脚本级:
1{
2 "color": "green",
3 "step": 2
4}
shared:
最佳实践